/*-----------------------------------------------------------------------------
	The contents of this file are subject to the Mozilla Public License
	Version 1.1 (the "License"); you may not use this file except in
	compliance with the License. You may obtain a copy of the License at
	http://www.mozilla.org/MPL/
	
	Software distributed under the License is distributed on an "AS IS"
	basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
	License for the specific language governing rights and limitations
	under the License.
	
	The Original Code is Fever Framework code.
	
	The Initial Developer of the Original Code is Romain Ecarnot.
	Portions created by Initial Developer are Copyright (C) 2006
	the Initial Developer. All Rights Reserved.
	
	Contributor(s):
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
-----------------------------------------------------------------------------*/

import org.aswing.BorderLayout;
import org.aswing.Component;
import org.aswing.Container;
import org.aswing.JButton;
import org.aswing.JLabel;
import org.aswing.JPanel;

import com.bourre.commands.Command;
import com.bourre.data.collections.Map;
import com.bourre.events.BooleanEvent;

import fever.data.file.File;
import fever.events.FeverController;
import fever.events.FeverEventList;
import fever.Fever;
import fever.utils.Stringifier;

import fvaswing.components.filechooser.events.FvPreviewEvent;
import fvaswing.components.filechooser.FvFileChooserResources;
import fvaswing.components.filechooser.mvc.FvFileChooserView;
import fvaswing.components.filechooser.preview.FvImagePreview;
import fvaswing.visual.FvViewHelper;

/**
 * Preview UI components for {@link fvaswing.components.FvFileChooser} 
 * component.
 * 
 * <p>You can specify preview behaviour using {@link #addPreviewCommand()} 
 * method and extending the 
 * {@link fvaswing.components.filechooser.preview.FvPreviewCommand} class.<br />
 * Take a look at {@link fvaswing.components.filechooser.preview.FvImagePreview} 
 * class for a concrete example.
 * 
 * @see fvaswing.components.filechooser.preview.FvImagePreview
 * @see fvaswing.components.filechooser.preview.FvPreviewCommand * 
 * @author Romain Ecarnot
 */
class fvaswing.components.filechooser.preview.FvChooserPreview extends FvViewHelper
{
	//-------------------------------------------------------------------------
	// Private properties
	//-------------------------------------------------------------------------
	
	private var _container : JPanel;
	private var _launchButton : JButton;
	private var _label : JLabel;
	private var _previewer : Component;
	
	private var _item : File;
	private var _typeMap : Map;
	private var _process : Command;
	
	private var _chooserTarget : MovieClip;
	 
	
	//-------------------------------------------------------------------------
	// Public API
	//-------------------------------------------------------------------------
	
	/**
	 * Constructor.
	 */
	public function FvChooserPreview()
	{
		super( _createContainer(), FvFileChooserView.PREVIEW );
		
		_typeMap = new Map();
		
		addPreviewCommand( 'jpg', new FvImagePreview() );		addPreviewCommand( 'png', new FvImagePreview() );
		
		_configureUI();
	}
	
	/**
	 * Stores a reference to the FileChooser MovieClip container.
	 */
	public function init( mcChooserTarget : MovieClip ) : Void
	{
		_chooserTarget = mcChooserTarget;
	}
	
	/**
	 * Returns a reference to the FileChooser MovieClip container.
	 * 
	 * <p>Can be used in concrete preview process.
	 */
	public function getChooserMovieTarget() : MovieClip
	{
		return _chooserTarget;
	}
	
	/**
	 * Prepares preloading of passed-in {@link fvaswing.components.filechooser.FvFileItem} 
	 * object.
	 */
	public function load( item : File ) : Void
	{
		_item = item;
		
		_previewer.removeFromContainer();
		
		if( item && _getPreviewProcess( item ) )
		{
			_displayEmptyPanel();
			if( item.getContent() != undefined ) _handleLaunchPreview();
			else _launchButton.setVisible( true );
			
		}
		else _displayErrorPanel();
	}
	
	/**
	 * Returns current main <strong>AsWing JPanel</strong>.
	 * 
	 * <p>Use by {@link fvaswing.components.filechooser.mvc.FvFileChooserView} 
	 * to append {@link FvChooserPreview} as component child.
	 */
	public function getContainer() : Container
	{
		return _container;	
	}
	
	/**
	 * Resets preview UI.
	 */
	public function reset() : Void
	{
		_displayEmptyPanel();	
	}
	
	/**
	 * Add new command to preview loader for passed-in {@code type} 
	 */
	public function addPreviewCommand( type : String, previewCommand : Command ) : Void
	{
		_typeMap.put( type, previewCommand );
	}
	
	/**
	 * Remove type to preview loader
	 */
	public function removeType( type : String ) : Void
	{
		_typeMap.remove( type );
	}
	
	/**
	 * Called by {@link fvaswing.components.filechooser.preview.FvPreviewCommand}
	 */
	public function handleResult( c : Component ) : Void
	{ 
		_changeTitle();
		
		_unlockUI();
		
		_launchButton.setVisible( false );
		_container.revalidateIfNecessary();
		
		_previewer.removeFromContainer();
		_previewer = c;
		
		_container.append( _previewer, BorderLayout.CENTER );
		_container.revalidateIfNecessary();
	}
	
	/**
	 * Called by {@link fvaswing.components.filechooser.preview.FvPreviewCommand}
	 */
	public function handleProgress( percent : Number ) : Void
	{
		_changeTitle( percent );	
	}
	
	/**
	 * Called by {@link fvaswing.components.filechooser.preview.FvPreviewCommand}
	 */
	public function handleError( ) : Void
	{ 
		_changeTitle();
		_unlockUI();
		
		_displayErrorPanel();
	}
	
	/**
	 * Returns string representation.
	 */
	public function toString() : String
	{
		return Stringifier.parse( this );
	}
	
	
	//-------------------------------------------------------------------------
	// Private implementation
	//-------------------------------------------------------------------------
	
	private function _configureUI() : Void
	{
		_launchButton = new JButton( FvFileChooserResources.getInstance().loadPreviewLabel );
		_launchButton.addActionListener( _handleLaunchPreview, this );
		_launchButton.setVisible( false );
		
		_label = new JLabel();
		
		_container.append( _launchButton, BorderLayout.SOUTH );
	}
	
	private function _createContainer() : Container
	{
		_container = new JPanel( new BorderLayout( 5, 5 ) );
		_container.setPreferredWidth( 100 );
		return _container;
	}
	
	private function _handleLaunchPreview( source : JButton ) : Void
	{
		_lockUI();
		
		_process.execute( new FvPreviewEvent( _item ) );
	}	
	
	/**
	 * Indicates whether the given file is accepted by this preview.
	 * 
	 * @return {@code true} if file is ok, otherwise {@code false}
	 */
	private function _getPreviewProcess( file : File ) : Boolean
	{
		if( file.isDirectory() ) return false;
      	
		var ext : String = file.getExtension();
		if( _typeMap.containsKey( file.getExtension() ) )
		{
			_process = _typeMap.get( ext );
			return true;
		}
		else return false;
	}
	
	private function _lockUI() : Void
	{
		FeverController.getInstance().broadcastEvent( new BooleanEvent( FeverEventList.onLockInteractionEVENT, true ) );
	}
	
	private function _unlockUI() : Void
	{ 
		FeverController.getInstance().broadcastEvent( new BooleanEvent( FeverEventList.onLockInteractionEVENT, false ) );
	}
	
	/**
	 * Display an 'unavailable' panel when preview type is not supported 
	 * or when an error occured during preview process. 
	 */
	private function _displayErrorPanel() : Void
	{
		_launchButton.setVisible( false );
		_label.setVisible( true );
		_label.setText( FvFileChooserResources.getInstance().noPreviewLabel);
			
		_container.append( _label, BorderLayout.CENTER );
		_container.revalidateIfNecessary();	
	}
	
	/**
	 * Display an 'empty panel at startup. 
	 */
	private function _displayEmptyPanel() : Void
	{
		_previewer.removeFromContainer();
		
		_launchButton.setVisible( false );
		_label.setVisible( false );
		
		_container.append( _label, BorderLayout.CENTER );
		_container.revalidateIfNecessary();
	}
	
	private function _changeTitle( n : Number ) : Void
	{
		if( n == undefined )
		{
			Fever.application.setTitle();
		}
		else Fever.application.setTitle( null, ' ( loading : ' + n + ' % )' );
	}
}